import { observer } from "./observer/index";
import { nextTick } from "./utils/nextTick";
import Watcher from './observer/watcher'
import Dep from './observer/dep'
export function initState(vm) {
	const opts = vm.$options;
	if (opts.data) {
		initData(vm);
	}
	if (opts.props) {
		initProps(vm);
	}
	if (opts.watch) {
		initWatch(vm);
	}
	if (opts.computed) {
		initComputed(vm);
	}
	if (opts.methods) {
		initMethods(vm);
	}
}

function initProps() { }

function initData(vm) {
	let data = vm.$options.data;
	data = vm._data = typeof data === "function" ? data.call(vm) : data;

	// 数据代理 以便于开发中以 this.xxx 形式获取
	for (const key in data) {
		if (Object.hasOwnProperty.call(data, key)) {
			proxy(vm, "_data", key);
		}
	}

	// 数据劫持
	observer(data);
}
function proxy(vm, source, key) {
	Object.defineProperty(vm, key, {
		get() {
			return vm[source][key];
		},
		set(newVal) {
			vm[source][key] = newVal;
		},
	});
}

function initWatch(vm) {
	const watch = vm.$options.watch;

	for (const key in watch) {
		const handler = watch[key];
		if (Array.isArray(handler)) {
			handler.forEach(fn => createWatcher(vm, key, fn));
		} else {
			createWatcher(vm, key, handler);
		}
	}
}

function createWatcher(vm, exprOrfn, handler, options) {
	if (typeof handler === "object") {
		options = handler;
		handler = handler.handler;
	}
	if (typeof handler === "string") {
		handler = vm[handler];
	}

	return vm.$watch(vm, exprOrfn, handler, options);
}


function initComputed(vm) {
	const computed = vm.$options.computed;
	let watcher = vm._computedWatchers = {};
	for (const key in computed) {
		const userDef = computed[key];
		const getter = typeof userDef === "function" ? userDef : userDef.get;
		watcher[key] = new Watcher(vm, getter, () => { }, { lazy: true }); //lazy 避免初始运算
		defineComputed(vm, key, userDef);
	}
	console.log(vm);
}
const sharedPropertyDefinition = {}
function defineComputed(target, key, userDef) {
	if (typeof userDef === "function") {
		sharedPropertyDefinition.get = createComputedGetter(key)
	} else {
		sharedPropertyDefinition.get = createComputedGetter(key);
		sharedPropertyDefinition.set = userDef.set;
	}
	// Object.defineProperty会创建不存在的属性
	Object.defineProperty(target, key, sharedPropertyDefinition);
}

function createComputedGetter(key) {
	return function () {
		let watcher = this._computedWatchers[key];
		if (watcher) {
			if (watcher.dirty) {
				watcher.evaluate();
			}
			if (Dep.target) {
				watcher.depend();
			}
			return watcher.value;
		}
	}
}

function initMethods() { }


export function stateMixin(vm) {
	vm.prototype.$nextTick = function (fn) {
		nextTick(fn);
	}
	vm.prototype.$watch = function (Vue, exprOrfn, handler, options) {

		const watcher = new Watcher(Vue, exprOrfn, handler, { ...options, user: true });
		// 立即执行
		if (options?.immediate) {
			handler(Vue)
		}
	}
}